/*
 * Copyright 2013-2018 Lilinfeng.
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.wish.nettyprotocol.codec;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.wish.nettyprotocol.struct.Header;
import com.wish.nettyprotocol.struct.NettyMessage;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;


/**
 * 自定义message解码类，最终还是调用封装jboss Marshaller的MyMarshallingDecoder
 *
 * @author tantexian
 * @since 2016/7/19
 */
    public class NettyMessageDecoder extends LengthFieldBasedFrameDecoder {

    MyMarshallingDecoder myMarshallingDecoder;

    /**
     * @author tantexian
     * @since 2016/7/21
     * maxFrameLength 1024*1024: 最大帧的长度，信息最大长度，超过这个长度会报异常
     * lengthFieldOffset 4: 长度属性的起始指针(偏移量)
     * lengthFieldLength 4: 长度属性的长度，即存放数据包长度的变量的的字节所占的长度
     */
    public NettyMessageDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength)
            throws IOException {
        super(maxFrameLength, lengthFieldOffset, lengthFieldLength);
        myMarshallingDecoder = new MyMarshallingDecoder();
    }


    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        ByteBuf frame = (ByteBuf) super.decode(ctx, in);
        if (frame == null) {
            return null;
        }

        NettyMessage message = new NettyMessage();
        Header header = new Header();
        // 依次读取解析header参数值
        header.setCrcCode(frame.readInt());
        header.setLength(frame.readInt());
        header.setSessionId(frame.readLong());
        header.setType(frame.readByte());
        header.setPriority(frame.readByte());

        // 解析读取header的attachment附件参数
        int size = frame.readInt();
        if (size > 0) {
            Map<String, Object> attch = new HashMap<String, Object>(size);
            int keySize = 0;
            byte[] keyArray = null;
            String key = null;
            for (int i = 0; i < size; i++) {
                keySize = frame.readInt();
                keyArray = new byte[keySize];
                frame.readBytes(keyArray);
                key = new String(keyArray, "UTF-8");
                attch.put(key, myMarshallingDecoder.decode(frame));
            }
            keyArray = null;
            key = null;
            header.setAttachment(attch);
        }
        // 消息类型 0-业务请求消息 1-业务响应消息 3-握手请求消息 4-握手应答消息 5-心跳请求消息 6-心跳应答消息
        if (frame.readableBytes() > 4) {
            message.setBody(myMarshallingDecoder.decode(frame));
        }
        message.setHeader(header);
        return message;
    }
}
